import { useEffect } from 'react'
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import * as CANNON from 'cannon-es';

import { CannonEsDebuggerPro } from '@vladkrutenyuk/cannon-es-debugger-pro';

function App() {
    useEffect(() => {

        // 创建世界
        const scene = new THREE.Scene();
        // 创建相机
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 设置相机位置 
        camera.position.z = 4;
        camera.position.x = 4;
        const root = new THREE.Group();
        scene.add(root); // 将根节点添加到场景中

        // 创建两个数组更新物理世界和threejs世界
        const cannonBodies = [];
        const threeObjects = [];


        // 创建物理世界
        const world = new CANNON.World();

        const color = 0xe60c0c; // or 'rgb(228, 14, 88)', '#e60c0c', 'red'
        const offset = 0.009;
        const cannonDebugger = new CannonEsDebuggerPro(root, world, color, offset);

        // 物理世界分组
        const group1 = 1; // 物理世界分组1
        const group2 = 2; // 物理世界分组2
        const group3 = 4; // 物理世界分组3
        const group4 = 8; // 物理世界分组4

        {
            // 设置重力
            world.gravity.set(0, -9.82, 0); // m/s²

            // 创建立方体
            const sphereShape = new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5));

            // 添加物理材质
            const boxMaterial = new CANNON.Material('boxMaterial'); // 创建材质
            boxMaterial.friction = 0; // 摩擦力

            // 添加光滑物理材质
            const boxSlipperyMaterial = new CANNON.Material('boxSlipperyMaterial');
            boxSlipperyMaterial.friction = 0; // 摩擦力

            // 添加弹性物理材质
            const boxElasticityMaterial = new CANNON.Material('boxElasticityMaterial');
            boxElasticityMaterial.friction = 0; // 摩擦力
            boxElasticityMaterial.restitution = 0.9; // 弹性

            // 盒子1 立方体
            {
                const sphereBody = new CANNON.Body({
                    mass: 1, // 质量
                    shape: sphereShape,
                    position: new CANNON.Vec3(0, 0, 0), // 初始位置
                    material: boxMaterial, // 使用摩擦力材质
                    collisionFilterGroup: group1, // 物理分组
                    collisionFilterMask: group2 | group3 | group4, // 碰撞分组
                });
                world.addBody(sphereBody);
                cannonBodies.push(sphereBody); // 添加到数组中

                // 设置移动
                sphereBody.velocity.set(2, 0, 0); // 设置速度

                // 碰撞事件
                sphereBody.addEventListener('collide', function (e) {
                    console.log('碰撞事件', e);
                    // 获取碰撞信息
                    const contact = e.contact; // 获取碰撞信息
                    const impactVelocity = contact.getImpactVelocityAlongNormal(); // 获取碰撞速度
                    console.log('碰撞速度', impactVelocity);

                    // 碰撞物体
                    // const bodyA = contact.bi; // 获取碰撞物体A
                    // const bodyB = contact.bj; // 获取碰撞物体B
                    // const positionA = bodyA.position; // 获取碰撞物体A位置
                    // const positionB = bodyB.position; // 获取碰撞物体B位置
                    // console.log('碰撞物体A', bodyA);
                    // console.log('碰撞物体B', bodyB);
                    // console.log('碰撞物体A位置', positionA);
                    // console.log('碰撞物体B位置', positionB);

                    if (impactVelocity > 1) { // 如果碰撞速度大于1
                        // 获取碰撞物体
                        console.log('碰撞');
                    }
                });
            }

            // 盒子2 圆球
            {
                const sphereShape = new CANNON.Sphere(0.5); // 创建圆球形状
                const sphereBody = new CANNON.Body({
                    mass: 1, // 质量
                    shape: sphereShape,
                    position: new CANNON.Vec3(2, 0, 0), // 初始位置
                    material: boxMaterial, // 使用光滑材质
                    collisionFilterGroup: group2, // 物理分组
                    collisionFilterMask: group1 | group4 // 碰撞分组
                });
                world.addBody(sphereBody);
                cannonBodies.push(sphereBody); // 添加到数组中
            }

            // 盒子3 圆柱
            {
                const sphereShape = new CANNON.Cylinder(0.5, 0.5, 1, 32); // 创建圆柱形状
                const sphereBody = new CANNON.Body({
                    mass: 1, // 质量
                    shape: sphereShape,
                    position: new CANNON.Vec3(4, 0, 0), // 初始位置
                    material: boxMaterial, // 使用弹性材质
                    collisionFilterGroup: group3, // 物理分组
                    collisionFilterMask: group1 | group4 // 碰撞分组
                });
                world.addBody(sphereBody);
                cannonBodies.push(sphereBody); // 添加到数组中
            }

            // 添加地面 摩擦力
            {
                const groundShape = new CANNON.Box(new CANNON.Vec3(5, 0.05, 5));
                const groundBody = new CANNON.Body({
                    mass: 0, // 质量为0表示静止物体
                    position: new CANNON.Vec3(0, -0.5, 0), // 初始位置
                    material: boxMaterial, // 使用摩擦力材质
                    collisionFilterGroup: group4, // 物理分组
                });
                groundBody.addShape(groundShape);
                world.addBody(groundBody);
            }

        }

        {
            {
                // 创建圆球
                const geometry = new THREE.BoxGeometry(1, 1, 1);
                // 创建材质
                const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
                // 创建网格
                const cube = new THREE.Mesh(geometry, material);
                // 将网格添加到场景中
                root.add(cube);
                threeObjects.push(cube); // 添加到数组中
            }
            {
                // 创建圆球
                const geometry = new THREE.SphereGeometry(0.5, 32, 32);
                // 创建材质
                const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
                // 创建网格
                const cube = new THREE.Mesh(geometry, material);
                // 将网格添加到场景中
                root.add(cube);
                threeObjects.push(cube); // 添加到数组中
            }
            {
                // 创建圆柱
                const geometry = new THREE.CylinderGeometry(0.5, 0.5, 1, 32);
                // 创建材质
                const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
                // 创建网格
                const cube = new THREE.Mesh(geometry, material);
                // 将网格添加到场景中
                root.add(cube);
                threeObjects.push(cube); // 添加到数组中
            }

            {
                // 创建平面
                const planeShape = new THREE.BoxGeometry(10, 0.1, 10);
                const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff });
                const plane = new THREE.Mesh(planeShape, planeMaterial);
                // 设置平面位置
                plane.position.y = -0.5;
                // 将平面添加到场景中
                scene.add(plane);
            }
        }



        // 创建渲染器
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 将渲染器添加到DOM中
        document.getElementById('app').appendChild(renderer.domElement);

        // 添加轨道控制器
        const controls = new OrbitControls(camera, renderer.domElement);

        // 创建动画函数
        const animate = function () {
            // 更新物理世界
            world.step(1 / 60); // 60fps
            // 更新threejs世界
            for (let i = 0; i < cannonBodies.length; i++) {
                const body = cannonBodies[i];
                const mesh = threeObjects[i];
                // 更新threejs物体的位置和旋转
                mesh.position.copy(body.position);
                mesh.quaternion.copy(body.quaternion);
            }
            cannonDebugger.update(); // 更新调试器

            // 更新轨道控制器
            controls.update();


            requestAnimationFrame(animate);

            // 渲染场景
            renderer.render(scene, camera);
        };
        // 调用动画函数
        animate();


        return () => {
            // 清除渲染器
            renderer.dispose();
            // 清除场景
            scene.clear();
            // 清除相机
            camera.clear();
            // 清除渲染器DOM
            const app = document.getElementById('app');
            if (app) {
                app.removeChild(renderer.domElement);
            }

        }
    }, [])
    return (
        <div id='app'>

        </div>
    )
}

export default App
